/**
 * \file AddIn.cpp
 *
 * \brief Implementation file for class CAddIn
 *
 * $Id: AddIn.cpp,v 1.1.1.1 2008/04/23 13:29:14 mgh Exp $
 *
 *
 * Copyright (C) 2006 Michael G. Herstine <sp1ff@pobox.com>
 *
 * Permission to use, copy, or modify this source code is hereby granted
 * free of  charge, provided  that this copyright  notice appear  on all
 * copies  and  on   all  source  code  derived  from   this  code.   No
 * representation is made regarding the suitability of this software for
 * any  purpose.  It  is provided  "as  is" without  express or  implied
 * warranty.
 *
 *
 */

#include "stdafx.h"             // Pre-compiled header for this project
#include "AddIn.h"              // Class CAddIn
#include "DSAddIn.h"            // Class CDSAddIn
#include "DTEAddIn.h"           // Class DTEAddIn
#include "ConfigDlg.h"          // Class CConfigDlg

////////////////////////////////////////////////////////////////////////

HRESULT
CSampleCAIModule::AddCommonRGSReplacements(IRegistrarBase* pRegistrar)
{
  USES_CONVERSION_EX;

  HRESULT hr =
    CAtlDllModuleT<CSampleCAIModule>::AddCommonRGSReplacements(pRegistrar);

  if (FAILED(hr)) return hr;

  // We're going to add a new replacement parameter: MODULE_PATH:
  HINSTANCE hInstance = _AtlBaseModule.GetModuleInstance();

  TCHAR lpszModule[MAX_PATH];
  DWORD dwLen = ::GetModuleFileName(hInstance, lpszModule, MAX_PATH);

  if ( 0 == dwLen )
  {
    return AtlHresultFromLastError();
  }
  else if ( MAX_PATH == dwLen )
  {
    return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  }

  if ( ! ::PathRemoveFileSpec(lpszModule) )
  {
    return AtlHresultFromLastError();
  }

  LPOLESTR lpszPath;
  lpszPath = T2OLE_EX(lpszModule, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);

  return pRegistrar->AddReplacement(OLESTR("MODULE_PATH"), lpszPath);

}

std::string getHelloPhrase()
{
  CRegKey hKey;
  LONG lStatus;

  lStatus = hKey.Create(HKEY_CURRENT_USER, SOFTWARE);
  ATLASSERT(ERROR_SUCCESS == lStatus);

  lStatus = hKey.Create(hKey, SAMPLES);
  ATLASSERT(ERROR_SUCCESS == lStatus);

  lStatus = hKey.Create(hKey, SAMPLECAI);
  ATLASSERT(ERROR_SUCCESS == lStatus);

  char lpszBuffer[MAX_HELLO_PHRASE];
  ULONG nBuffer = MAX_HELLO_PHRASE;
  lStatus = hKey.QueryStringValue(VAL_HELLO_PHRASE, lpszBuffer, &nBuffer);

  if (ERROR_SUCCESS == lStatus) return std::string(lpszBuffer);
  else                          return DEF_HELLO_PHRASE;
}

void setHelloPhrase(const std::string &strText)
{
  CRegKey hKey;
  LONG lStatus;

  lStatus = hKey.Create(HKEY_CURRENT_USER, SOFTWARE);
  ATLASSERT(ERROR_SUCCESS == lStatus);

  lStatus = hKey.Create(hKey, SAMPLES);
  ATLASSERT(ERROR_SUCCESS == lStatus);

  lStatus = hKey.Create(hKey, SAMPLECAI);
  ATLASSERT(ERROR_SUCCESS == lStatus);

  lStatus = hKey.SetStringValue(VAL_HELLO_PHRASE, strText.c_str());
  ATLASSERT(ERROR_SUCCESS == lStatus);
}

////////////////////////////////////////////////////////////////////////
// Class CAddIn

CAddIn::CAddIn()
{}

/**
 * \brief ATL-defined initialization routine
 *
 *
 * \return S_OK on success, a failed HRESULT on failure to abort
 * instance creation
 *
 *
 * Here is where we aggregate our sub-objects.
 *
 *
 * \todo Move to some sort of cached scheme to avoid instantiating an
 * instance of, say, CoDTEAddIn when we're loaded into DevStudio...
 *
 *
 */

HRESULT CAddIn::FinalConstruct()
{
  ATLTRACE2(atlTraceCOM, 2, "CAddIn::FinalConstruct\n");

  HRESULT hr = S_OK;
  IUnknown *pOuterUnk = GetControllingUnknown();

  hr = CreateInstanceWithParamItf(pOuterUnk, this, &m_pDSAddIn,
                                  (CComAggObject<CDSAddIn>**)NULL);
  if (FAILED(hr)) return hr;

  hr = CreateInstanceWithParamItf(pOuterUnk, this, &m_pDTEAddIn,
                                  (CComAggObject<CDTEAddIn>**)NULL);
  if (FAILED(hr)) return hr;

  return S_OK;
}

/**
 * \brief ATL-defined cleanup routine
 *
 *
 * \note We release our references on our aggregates in this routine
 *
 *
 */

void CAddIn::FinalRelease()
{
  ATLTRACE2(atlTraceCOM, 2, "CAddIn::FinalRelease\n");

  m_pDSAddIn  = NULL;           // Release our references
  m_pDTEAddIn = NULL;
}

////////////////////////////////////////////////////////////////////////
// Interface ISupportsErrorInfo

STDMETHODIMP CAddIn::InterfaceSupportsErrorInfo(/*[in]*/ REFIID riid)
{
  static const IID* arr[] = { &IID_IDSAddIn,
                              &EnvDTE::IID_IDTCommandTarget,
                              &AddInDesignerObjects::IID__IDTExtensibility2,
  };

  for (int i = 0; i < sizeof(arr)/sizeof(arr[0]); ++i)
  {
    if (InlineIsEqualGUID(*arr[i],riid)) return S_OK;
  }

  return S_FALSE;
}

////////////////////////////////////////////////////////////////////////

void CAddIn::Configure()
{
  ATLTRACE2(atlTraceCOM, 2, "CAddIn::Configure\n");

  std::string strHello = getHelloPhrase();

  CConfigDlg dlg(strHello);
  if (IDOK == dlg.DoModal())
  {
    setHelloPhrase(dlg.getHello());
  }
}

void CAddIn::SayHello()
{
  ATLTRACE2(atlTraceCOM, 2, "CAddIn::SayHello\n");

  std::string strHello = getHelloPhrase();

  ::MessageBoxA(NULL, strHello.c_str(), _T("Common AddIns Sample"), MB_OK);
}

// Local Variables:
// fill-column: 72
// indent-tabs-mode: nil
// show-trailing-whitespace: t
// End:

// AddIn.cpp ends here.
